package com.weishi.project.speedometer.service.impl;

import com.weishi.project.speedometer.service.IWitService;
import com.weishi.project.speedometer.vo.PropellerFrequencyData;
import com.weishi.project.speedometer.vo.PropellerFrequencyWitVo;
import com.weishi.project.training.domain.TrainingGroupChannel;
import com.weishi.project.training.domain.WitAccLog;
import com.weishi.project.training.service.ITrainingGroupChannelService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class IWitServiceImpl implements IWitService {

    private Map<String, List<WitAccLog>> queue = new HashMap<>();

    @Autowired
    Environment environment;

    @Autowired
    private ITrainingGroupChannelService trainingGroupChannelService;

    @Override
    public void addTempList(WitAccLog vo) {

        List<WitAccLog> list = queue.get(vo.getDevId());
        if (list == null) {
            list = new ArrayList<>();
            queue.put(vo.getDevId(), list);
        }
        list.add(vo);
    }

    @Override
    public void clearTempList(String deviceId) {
        List<WitAccLog> list = queue.get(deviceId);
        list.clear();
    }

    @Override
    public List<WitAccLog> getList(String deviceId) {
        List<WitAccLog> list = null;
        try {
            list = queue.get(deviceId);
            if (list == null) list = new ArrayList<>();
        } catch (Exception e) {
            e.printStackTrace();
            clearTempList(deviceId);
        }
        return list;
    }

    @Override
    public List<PropellerFrequencyData> getPropellerFrequencyData(List<WitAccLog> dataVos, int count) {
        List<PropellerFrequencyWitVo> list = getImportantPoint(dataVos);
        List<PropellerFrequencyData> ret = new ArrayList<>();

        for (int i = 0; i < list.size(); i++) {
            PropellerFrequencyData data = new PropellerFrequencyData();
            data.setCount(count);
            if (list.get(i).getType() == -1) {
                data.setStartTime(list.get(i).getRealTime());
                data.setStartTimeTimp(list.get(i).getTimeTimp());

                if ((i + count * 2) < list.size()) {
                    data.setDistanceTotal(list.get(i + count * 2).getDistanceTotal());
                    data.setDistance(list.get(i + count * 2).getDistanceTotal() - list.get(i).getDistanceTotal());
                    data.setEndTime(list.get(i + count * 2).getRealTime());
                    data.setEndTimeTimp(list.get(i + count * 2).getTimeTimp());
                    double minute = (data.getEndTimeTimp() - data.getStartTimeTimp()) / 1000.0;
                    double averagePropeller = count / (minute / 60.0);
                    if (averagePropeller > 150) {
                        averagePropeller = 140;
                    }
                    data.setAveragePropeller(averagePropeller);
                } else {
                    PropellerFrequencyWitVo temp = (i + count * 2) <= list.size() ? list.get(i + count) : list.get(i);
                    data.setEndTime(temp.getRealTime());
                    data.setEndTimeTimp(temp.getTimeTimp());
                    data.setDistanceTotal(temp.getDistanceTotal());
                    data.setDistance(temp.getDistanceTotal() - list.get(i).getDistanceTotal());
                    double minute = (data.getEndTimeTimp() - data.getStartTimeTimp()) / 60000.0;
                    double averagePropeller = minute != 0 ? 1 / minute : 0.0;
                    if (averagePropeller > 150) {
                        averagePropeller = 140;
                    }
                    data.setAveragePropeller(averagePropeller);
                }
                data.setRealTime(data.getEndTime());

                ret.add(data);
            }
        }
        return ret;
    }

    /**
     * 获取波峰波谷
     *
     * @param dataVos
     * @return
     */
    private List<PropellerFrequencyWitVo> getImportantPoint(List<WitAccLog> dataVos) {

        String type = environment.getProperty("system.version");
        //测试环境的艇种根据登陆账号区分
        if(type.equals("demo") && dataVos!=null && dataVos.size()>0){
            TrainingGroupChannel trainingGroupChannel = trainingGroupChannelService.getById(dataVos.get(0).getChannelId());
            String devId = trainingGroupChannel.getShipSpeedId();
            type = devId.contains("HT") ? "h" : devId.contains("PT") ? "p" : "s";
        }

        List<PropellerFrequencyWitVo> dataVoList = null;
        try {
            dataVoList = new ArrayList<>();

            List<Double> distances = new ArrayList<>();
            for (WitAccLog gpsVo : dataVos) {
                if(type.equals("h")){
                    distances.add(gpsVo.getAnglez());
                }else if(type.equals("p")){
                    distances.add(gpsVo.getAngley());
                }else{
                    distances.add(gpsVo.getAnglex());
                }
            }
            double[] data = new double[dataVos.size()];
            int index = 0;
            for (Double aa : distances) {
                data[index++] = aa;
            }
            int peak = 0;

            try {
                int[] PeakAndTrough = new int[data.length];

                //需要三个不同的值进行比较，取lo,mid，hi分别为三值
                for (int lo = 0, mid = 1, hi = 2; hi < data.length; hi++) {
                    //先令data[lo]不等于data[mid]
                    while (mid < data.length && data[mid] == data[lo]) {
                        mid++;
                    }

                    hi = mid + 1;

                    //令data[hi]不等于data[mid]
                    while (hi < data.length && data[hi] == data[mid]) {
                        hi++;
                    }

                    if (hi >= data.length) {
                        break;
                    }

                    //检测是否为峰值
                    if (data[mid] > data[lo] && data[mid] > data[hi]) {
                        PeakAndTrough[mid] = 1;       //1代表波峰
                    } else if (data[mid] < data[lo] && data[mid] < data[hi]) {
                        PeakAndTrough[mid] = -1;      //-1代表波谷
                    }

                    lo = mid;
                    mid = hi;
                }

                //计算均值
                float ave = 0;
                for (int i = 0; i < data.length; i++) {
                    ave += data[i];
                }
                ave /= data.length;


                //排除大于均值的波谷和小于均值的波峰
                /*for (int i = 0; i < PeakAndTrough.length; i++) {
                    if ((PeakAndTrough[i] > 0 && data[i] < ave) || (PeakAndTrough[i] < 0 && data[i] > ave)) {
                        PeakAndTrough[i] = 0;
                    }
                }*/

                //统计波谷数量
                for (int i = 0; i < PeakAndTrough.length; i++) {
                    if (PeakAndTrough[i] != 0) {
                        PropellerFrequencyWitVo vo = new PropellerFrequencyWitVo();
                        vo.setType(PeakAndTrough[i]);
                        vo.setRealTime(dataVos.get(i).getTimp());
                        vo.setTimeTimp(Long.parseLong(dataVos.get(i).getTimp()));
                        vo.setWitAccLog(dataVos.get(i));
                        dataVoList.add(vo);

                        dataVos.get(i).setNode(PeakAndTrough[i]);
                    }
                }

                //旋转角度大于40度为有效桨 划艇：80  皮艇：120  赛艇：180
                List<PropellerFrequencyWitVo> remove = new ArrayList<>();
                PropellerFrequencyWitVo pre = null;
                for (PropellerFrequencyWitVo vo : dataVoList) {
                    if(pre==null){
                        pre = vo;
                        continue;
                    }
                    WitAccLog witDataVo = vo.getWitAccLog();
                    if (pre.getWitAccLog().getAnglex() - witDataVo.getAnglex() > 60 || witDataVo.getAnglex() - pre.getWitAccLog().getAnglex() > 60) {
                        pre = vo;
                    }else{
                        vo.setType(0);
                        witDataVo.setNode(0);
                        remove.add(vo);
                    }

                }

                //去除因角度旋转不够删除的波峰波谷
                dataVoList.removeAll(remove);


            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataVoList;
    }

}
